﻿using System;
using System.Windows;
using System.Windows.Controls;
using Sonce.Common;
using Sonce.Editor;
using Sonce.Editor.Tools;

namespace Sonce.Core
{
	/// <summary>
	/// This is a partial extension for the Page class. Includes methods that are not bound directly to GUI.
	/// </summary>
	public partial class Page : UserControl
	{
		#region Members
		private Utils utils = null;
		private DocumentManager documentManager = null;
		//private CompileService compileService = null;

		private OrtoLines ortoLine = OrtoLines.None;
		#endregion

		#region Initialization
		/// <summary>
		/// Partial class initialization.
		/// </summary>
		protected void InitializeCommon()
		{
			this.utils = new Utils(App.Current, this);
			this.documentManager = new DocumentManager();
		}
		#endregion

		#region Methods
		/// <summary>
		/// Update size of elements. This method should be called on resize.
		/// </summary>
		private void updateSize()
		{
			try
			{
				double width = App.Current.Host.Content.ActualWidth;
				double height = App.Current.Host.Content.ActualHeight;

				this.Width = width;
				this.Height = height;
				//toolbar.Width = width;
				//sidebar.Height = height - 35;
				//gridbar.Width = width;
				//tabs.Width = width - 220;
				//tabs.Height = height - 250;
				//scroll.Width = width - 220;
				//scroll.Height = height - 185;
				//scroll2.Width = width - 220;

				//text.Width = scroll.Width;
				//text.Height = scroll.Height;
			}
			catch (Exception ex)
			{
				Logger.Log(ex, LogLevels.Detailed);
			}
		}

		/// <summary>
		/// Update icons and other elements that can be locked (i.e. disabled when cannot be used).
		/// </summary>
		private void updateControls()
		{
			//Dictionary<string, bool> isEnabled = editor.GetAllowedActions();
			//iconUndo.Enabled = isEnabled["Undo"];
			//iconRedo.Enabled = isEnabled["Redo"];
		}

		/// <summary>
		/// Overloaded. Execute a command without arguments.
		/// </summary>
		/// <param name="command"></param>
		private void runCommand(string command)
		{
			runCommand(new Command(command, null));
		}

		/// <summary>
		/// Overloaded. Execute a command with additional arguments.
		/// </summary>
		/// <param name="command"></param>
		/// <param name="args"></param>
		private void runCommand(string command, string args)
		{
			runCommand(new Command(command, args));
		}

		/// <summary>
		/// Overloaded. Execute a command.
		/// </summary>
		/// <param name="command"></param>
		private void runCommand(ICommand command)
		{
			try
			{
				runCommand((Commands)Enum.Parse(typeof(Commands), command.Name, true), command.Value);
			}
			catch (Exception ex)
			{
				Logger.Log(ex, LogLevels.Detailed);
			}
		}

		/// <summary>
		/// Overloaded. Execute a command without arguments.
		/// </summary>
		/// <param name="command"></param>
		private void runCommand(Commands command)
		{
			runCommand(command, null);
		}

		/// <summary>
		/// Execute a command with additional arguments.
		/// </summary>
		/// <param name="command">Command from Commands enum.</param>
		/// <param name="value">Optional. Additional arguments or command value.</param>
		private void runCommand(Commands command, object value)
		{
			#region Cast
			bool bValue = (value is bool ? (bool)value : default(bool));
			int iValue = (value is int ? (int)value : default(int));
			double dValue = (value is double ? (double)value : default(double));
			string sValue = (value as string ?? null);
			#endregion

			switch (command)
			{
				#region File
				case Commands.New:
					this.documentManager.New();
					editor.Reload();
					//console.Clear();
					break;

				case Commands.Open:
					this.documentManager.Open();
					//console.WriteLine("Open");
					break;

				case Commands.Save:
					this.documentManager.Save();
					break;

				case Commands.SaveAs:
					this.documentManager.Save();
					break;
				#endregion

				#region Edit
				case Commands.Undo:
					editor.Undo();
					updateControls();
					break;

				case Commands.Redo:
					editor.Redo();
					updateControls();
					break;

				case Commands.Cut:
					editor.Cut();
					updateControls();
					break;

				case Commands.Copy:
					editor.Copy();
					updateControls();
					break;

				case Commands.Paste:
					editor.Paste();
					updateControls();
					break;
				#endregion

				#region View
				case Commands.ViewTool:
					editor.SelectedTool = new ViewTool();
					break;

				case Commands.Pan:
					editor.SelectedTool = new PanTool();
					break;

				case Commands.Zoom:
					editor.SelectedTool = new ZoomTool();
					break;

				case Commands.ZoomIn:
					//editor.Zoom += (d != double.NaN ? d : 0.1); //Default is 10%
					editor.Zoom += 0.1;
					Logger.WriteLine("Zoom: " + editor.Zoom * 100 + "%");
					break;

				case Commands.ZoomOut:
					//editor.Zoom -= (d != double.NaN ? d : 0.1); //Default is 10%
					editor.Zoom -= 0.1;
					Logger.WriteLine("Zoom: " + editor.Zoom * 100 + "%");
					break;
				#endregion

				#region Tools
				case Commands.OrtoLineNone:
					this.ortoLine = OrtoLines.None;
					break;

				case Commands.OrtoLineAngle90:
					this.ortoLine = OrtoLines.Angle90;
					break;

				case Commands.OrtoLineAngle45:
					this.ortoLine = OrtoLines.Angle45;
					break;

				case Commands.OrtoLineCombo90:
					this.ortoLine = OrtoLines.Combo90;
					break;

				case Commands.OrtoLineCombo45:
					this.ortoLine = OrtoLines.Combo45;
					break;

				case Commands.HandTool:
					editor.SelectedTool = new HandTool();
					break;

				case Commands.LineTool:
					editor.SelectedTool = new LineTool(LineTypes.Line, this.ortoLine);
					break;

				case Commands.PolyLineTool:
					editor.SelectedTool = new LineTool(LineTypes.PolyLine, this.ortoLine);
					break;

				case Commands.RefLineTool:
					editor.SelectedTool = new LineTool(LineTypes.RefLine, this.ortoLine);
					break;

				case Commands.RectTool:
					editor.SelectedTool = new ShapeTool(ShapeTool.Shapes.Rectangle);
					break;

				case Commands.NodeTool:
					editor.SelectedTool = new NodeTool();
					break;

				case Commands.ElementTool:
					editor.SelectedTool = new ElementTool(value as ElementTag);
					break;

				case Commands.TextTool:
					editor.SelectedTool = new TextTool();
					break;
				#endregion

				#region Order
				case Commands.MoveToFront:
					editor.MoveToFront();
					break;

				case Commands.MoveToBack:
					editor.MoveToBack();
					break;

				case Commands.MoveForward:
					editor.MoveForward();
					break;

				case Commands.MoveBackward:
					editor.MoveBackward();
					break;
				#endregion

				#region Align
				case Commands.AlignLeft:
					editor.Align(AlignDirections.Left);
					break;

				case Commands.AlignRight:
					editor.Align(AlignDirections.Right);
					break;

				case Commands.AlignTop:
					editor.Align(AlignDirections.Top);
					break;

				case Commands.AlignBottom:
					editor.Align(AlignDirections.Bottom);
					break;
				#endregion

				#region Transitions
				case Commands.Scale:
					//TODO: Show pop-up to enter dimensions
					//editor.Scale();
					break;

				case Commands.FlipVertical:
					editor.Flip(false, true);
					break;

				case Commands.FlipHorizontal:
					editor.Flip(true, false);
					break;

				case Commands.FlipBoth:
					editor.Flip(true, true);
					break;

				case Commands.RotateLeft:
					editor.Angle -= 45;
					//editor.Rotate(RotateDirections.Left);
					break;

				case Commands.RotateRight:
					editor.Angle += 45;
					//editor.Rotate(RotateDirections.Right);
					break;
				#endregion

				#region Selection
				case Commands.SelectAll:
					editor.SelectionManager.SelectAll();
					Logger.WriteLine("Select all");
					break;

				case Commands.UnselectAll:
					editor.SelectionManager.UnselectAll();
					Logger.WriteLine("Unselect all");
					break;

				case Commands.DeleteSelected:
					editor.Delete();
					Logger.WriteLine("Delete selected");
					break;

				case Commands.GroupSelected:
					editor.SelectionManager.Group();
					break;

				case Commands.UngroupSelected:
					editor.SelectionManager.Ungroup();
					break;
				#endregion

				#region Application
				case Commands.ToggleEditor:
					//if (text.Visibility == Visibility.Visible)
					//{
					//    text.Visibility = Visibility.Collapsed;
					//}
					//else
					//{
					//    text.Visibility = Visibility.Visible;
					//    //text.Text = Sonce.Common.Converter.FrameworkElementToString(editor.LayerCircuit);
					//    text.Text = "(no export available)";
					//}
					break;

				case Commands.Fullscreen:
					utils.ToggleFullscreen();
					Logger.WriteLine("Fullscreen: " + App.Current.Host.Content.IsFullScreen);
					break;

				case Commands.FullscreenStretch:
					utils.ToggleStretch();
					//Download test,testing security 
					//WebClient client = new WebClient();
					//client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
					//client.DownloadStringAsync(new Uri("http://localhost/spice/index.php", UriKind.Absolute));
					break;
				#endregion

				#region Other
				case Commands.RandomRectangles:
					Random random = new Random();
					int max = 100;
					DateTime start = DateTime.Now;
					ShapeTool tool = new ShapeTool() { Editor = editor };
					for (int i = 0; i < max; i++)
					{
						double x1 = random.NextDouble() * 800;
						double y1 = random.NextDouble() * 600;
						double x2 = random.NextDouble() * 800;
						double y2 = random.NextDouble() * 600;
						tool.DrawRectangle(editor.LayerWorking, new Point(x1, y1), new Point(x2, y2));
					}
					DateTime end = DateTime.Now;
					TimeSpan duration = end.Subtract(start);
					string message = string.Format("{0} random rectangles loaded. Duration: {1}", max, duration);
					Logger.WriteLine(message);
					break;

				case Commands.Compile:
					//this.compileService = new CompileService();
					//this.compileService.CompileCompleted += new EventHandler<CompileServiceEventArgs>(compileService_CompileCompleted);
					//this.compileService.Compile(text.Text, "compile");
					break;

				case Commands.Test:
					//utils.ForceDownload("Testing ForceDownload() method.", "test.txt", "plain/text", true);
					//Repository.Export();

					//Repository.LoadTestData();
					//var x = from i in Repository.ElementPrototypes
					//        where i.ID == 103
					//        select i;
					//int count = x.Count();

					//this.editor.GroupSelected();

					this.editor.SelectedTool = new TextTool("hello");
					break;

				case Commands.JavaScript:
					utils.RunJavascript(sValue);
					break;
				#endregion
			}
		}
		#endregion
	}
}
